Pre-populating a Database with Data in Vapor

If your database needs some pre-populated data, that process is done in Vapor via migrations.


Structure your project

My workflow for creating a migration for some model is:

  1. Exit Xcode
  1. Make /App/Migrations directory
  1. Make /App/Migrations/Populate.swift file
  1. Generate Xcode Project

Make the Migration class

Make a new class that conforms to Migration protocol:

import FluentPostgreSQL

final class PopulateForms: Migration {
  typealias Database = PostgreSQLDatabase
  
  static let formNames = [
    "powder",
    "seed",
    "whole",
    "granules"
  ]
  
  static func prepare(on connection: PostgreSQLConnection) -> Future<Void> {
    // Insert all forms from formNames
    let futures = formNames.map { name in
      return Form(name: name).create(on: connection).map(to: Void.self) { _ in return }
    }
    return Future<Void>.andAll(futures, eventLoop: connection.eventLoop)
  }
  
  static func revert(on connection: PostgreSQLConnection) -> Future<Void> {
    do {
      // Delete all names
      let futures = try formNames.map { name in
        return try Form.query(on: connection).filter(\Form.name == name).delete()
      }
      return Future<Void>.andAll(futures, eventLoop: connection.eventLoop)
    }
    catch {
      return connection.eventLoop.newFailedFuture(error: error)
    }
  }
}


You need to specify the Database alias:

typealias Database = PostgreSQLDatabase

And implement methods for adding and deleting data:

static func prepare(on connection: PostgreSQLConnection) -> Future<Void> {}
static func revert(on connection: PostgreSQLConnection) -> Future<Void> {}

With the appropriate database connection type.


Add the migration to the config

Call the migration from the configure.swift file:

  /// Configure migrations
  var migrations = MigrationConfig()
  migrations.add(model: Tip.self, database: .psql)
  migrations.add(model: Season.self, database: .psql)
  
  migrations.add(model: Form.self, database: .psql)
  //pre-populate form names with PopulateForms.self migration
  migrations.add(migration: PopulateForms.self, database: .psql)
  
  services.register(migrations)

Just make sure that the model object Form here, is added to the migrations before the PopulateForms.


When you run your app, you will see the migrations taking place, in Xcode’s console:

[ INFO ] Migrating 'psql' database (FluentProvider.swift:28)
[ INFO ] Preparing migration 'Tip' (MigrationContainer.swift:50)
[ INFO ] Preparing migration 'Season' (MigrationContainer.swift:50)
[ INFO ] Preparing migration 'Form' (MigrationContainer.swift:50)
[ INFO ] Preparing migration 'PopulateForms' (MigrationContainer.swift:50)
[ INFO ] Migrations complete (FluentProvider.swift:32)
Running default command: /Users/mmj/Developer/me/vap/tastee/DerivedData/tastee/Build/Products/Debug/Run serve
Server starting on http://localhost:8080

Prev: Adding Foreign Keys to a Database in Vapor

Next: Pre-populating Related Tables in Vapor


Vapor 3 Tutorial Start


#pub #db #postgresql #vapor #swift #ddl #migration #pre-populate